package com.next

import freemarker.template.Configuration
import freemarker.template.DefaultObjectWrapper
import freemarker.template.Template
import grails.converters.JSON
import grails.gorm.transactions.Transactional
import net.sf.jasperreports.engine.JRExporterParameter
import net.sf.jasperreports.engine.export.JRPdfExporter
import nine.jasper.JasperService
import nine.jasper.spring.JasperReportDef
import nine.reports.ReportFormat
import org.apache.commons.lang.StringUtils
import org.springframework.security.access.annotation.Secured

import javax.servlet.ServletContext
import java.text.SimpleDateFormat

@Secured(['ROLE_ADMINISTRATOR', 'ROLE_CUSTOMER_SERVICE_REPRESENTATIVE', 'ROLE_ACCOUNT_MANAGER', 'ROLE_COMPANY_ADMINISTRATOR', 'ROLE_PRODUCT_ADMINISTRATOR', 'ROLE_GENERAL_RISK_MANAGER', 'ROLE_BRANCH_OFFICE_RISK_MANAGER', 'ROLE_HEAD_OFFICE_RISK_MANAGER', 'ROLE_GENERAL_MANAGER', 'ROLE_CRO', 'ROLE_CEO', 'ROLE_COO', 'ROLE_BRANCH_GENERAL_MANAGER', 'ROLE_BRANCH_OFFICE_CASHIER', 'ROLE_BRANCH_OFFICE_POST_LOAN_MANAGER'])
@Transactional(readOnly = true)
class OpportunityStatisticsController
{
    static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
    def billsService
    def opportunityService
    def contactservice
    def springSecurityService
    JasperService jasperService

    def exportContract()
    {
        def opportunity = Opportunity.findById(params["opportunity"])
        def templateFile = "templet/bbb.ftl"
        def beanParams = [:]
        def contratct = OpportunityContract.find("from OpportunityContract where opportunity.id = ${opportunity.id} and contract.type.name ='借款合同' ")?.contract?.serialNumber
        def fullName = opportunity.fullName
        def contact = OpportunityContact.findByOpportunityAndType(opportunity, OpportunityContactType.findByName("借款人"))?.contact
        if (!contact)
        {
            contact = OpportunityContact.findByOpportunityAndType(opportunity, OpportunityContactType.findByName("借款人"))?.contact
        }
        def idNumber = contact?.idNumber
        def cellphone = contact?.cellphone
        String bigC = billsService.transforNumToRMB(opportunity.actualAmountOfCredit)
        def bigAmount = bigC.substring(0, bigC.lastIndexOf("元"))
        Integer i = opportunity.actualAmountOfCredit
        def amount = "${i}"
        def loanAmount = "${opportunity.actualLoanDuration}个月"
        def bankAccount = OpportunityBankAccount.findByOpportunityAndType(opportunity, OpportunityBankAccountType.findByName("收款账号"))?.bankAccount
        def accountName = bankAccount?.name
        def bankAccountOfNumber = bankAccount?.numberOfAccount
        def bankName = bankAccount?.bank?.name
        def rate = OpportunityProduct.find("from OpportunityProduct where opportunity.id = ${opportunity.id}  and productInterestType.name = '基本费率'")?.rate
        beanParams.put("contractNO", contratct == null ? "" : contratct)
        beanParams.put("fullName", fullName == null ? "" : fullName)
        beanParams.put("idNumber", idNumber == null ? "" : idNumber)
        beanParams.put("cellphone", cellphone == null ? "" : cellphone)
        beanParams.put("bigAmount", bigAmount == null ? "" : bigAmount)
        beanParams.put("amount", amount == null ? "" : amount)
        beanParams.put("loanAmount", loanAmount == null ? "" : loanAmount)
        beanParams.put("accountName", accountName == null ? "" : accountName)
        beanParams.put("accountNumber", bankAccountOfNumber == null ? "" : bankAccountOfNumber)
        beanParams.put("bankName", bankName == null ? "" : bankName)
        beanParams.put("rate", rate == null ? "" : rate + "%")
        Configuration config = new Configuration()
        ServletContext sc = request.getSession().getServletContext()
        InputStream is
        File previewFile
        try
        {
            config.setDirectoryForTemplateLoading(new File(sc.getRealPath("/")))
            config.setObjectWrapper(new DefaultObjectWrapper())
            Template template = config.getTemplate(templateFile, "UTF-8")
            def docFileName = "个人借款合同.doc"
            String docName = request.getSession().getServletContext().getRealPath("/") + docFileName
            FileOutputStream fos = new FileOutputStream(docName)
            Writer out = new OutputStreamWriter(fos, "UTF-8")
            template.process(beanParams, out)
            out.flush()
            out.close()

            previewFile = new File(docName)
            is = new FileInputStream(previewFile)
            response.reset()
            if (true)
            {
                response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=GBK")
            }
            else
            {
                response.setContentType("application/vnd.ms-word;charset=GBK")
            }
            response.addHeader("Content-Disposition", "attachment;filename=LoanContract.doc")
            byte[] b = new byte[1024]
            int len
            while ((len = is.read(b)) > 0)
            {
                response.getOutputStream().write(b, 0, len)
            }
            response.getOutputStream().flush()
            response.getOutputStream().close()
        }
        catch (Exception e)
        {
            e.printStackTrace()
        }
        finally
        {
            if (is != null)
            {
                try
                {
                    is.close()
                }
                catch (IOException e)
                {
                    e.printStackTrace()
                }
            }
            if (previewFile != null)
            {
                previewFile.delete()
            }
        }
    }

    @Transactional
    @Secured(['ROLE_ADMINISTRATOR', 'ROLE_CUSTOMER_SERVICE_REPRESENTATIVE', 'ROLE_ACCOUNT_MANAGER', 'ROLE_COMPANY_ADMINISTRATOR', 'ROLE_GENERAL_RISK_MANAGER', 'ROLE_BRANCH_OFFICE_RISK_MANAGER', 'ROLE_HEAD_OFFICE_RISK_MANAGER', 'ROLE_GENERAL_MANAGER', 'ROLE_CRO', 'ROLE_CEO', 'ROLE_COO', 'ROLE_BRANCH_GENERAL_MANAGER'])
    def edit(Opportunity opportunity)
    {
        opportunity = Opportunity.findById(opportunity.id)
        respond opportunity, model: [opportunity: opportunity]
    }

    @Secured(['ROLE_ADMINISTRATOR', 'ROLE_CUSTOMER_SERVICE_REPRESENTATIVE', 'ROLE_ACCOUNT_MANAGER', 'ROLE_COMPANY_ADMINISTRATOR', 'ROLE_GENERAL_RISK_MANAGER', 'ROLE_BRANCH_OFFICE_RISK_MANAGER', 'ROLE_HEAD_OFFICE_RISK_MANAGER', 'ROLE_GENERAL_MANAGER', 'ROLE_CRO', 'ROLE_CEO', 'ROLE_COO', 'ROLE_BRANCH_GENERAL_MANAGER'])
    @Transactional
    def update(Opportunity opportunity)
    {
        opportunity = Opportunity.findById(params.id)
        opportunity.setMemo(params.memo)
        opportunity.save()
        redirect(controller: "opportunityStatistics", action: "dailyReportList")
        return
    }

    /**
     * @Description 放款台账 贷后
     * @Author yuanchao* @Return
     * @DateTime 2017/9/8 10:44
     */
    @Secured(['ROLE_ADMINISTRATOR', 'ROLE_COO', 'ROLE_BRANCH_OFFICE_POST_LOAN_MANAGER'])
    @Transactional
    def loanReport(Integer max)
    {
        def username = springSecurityService.getPrincipal().username
        def user = User.findByUsername(username)
        //分页
        params.max = 10
        params.offset = params.offset ? params.offset.toInteger() : 0
        max = 10
        def offset = params.offset
        //下载
        def report = params.report
        //搜索条件
        def loanDate = params.loanDate
        def endDate = params.endDate
        def city = params.city
        def product = params.product
        def fullName = params.fullName
        def contract = params.contract
        def jqStatus = params.jqStatus
        def jqDate = params.jqDate
        def sql = "select distinct o.id  from Opportunity o , House c ,OpportunityContract oc , Bills b where  c.opportunity.id = o.id and oc.opportunity.id = o.id and  b.opportunity.id  = o.id "
        if (loanDate)
        {
            sql += "  and  CONVERT(varchar(100), o.actualLendingDate, 120) like '${loanDate}%'"
        }

        if (fullName)
        {
            sql += " and o.fullName like '%${fullName}%'"
        }
        if (product && product != 'null')
        {
            sql += " and o.product.name = '${product}'"
        }
        //判断是否为贷后经理
        if (UserRole.findByUserAndRole(user, Role.findByAuthority("ROLE_BRANCH_OFFICE_POST_LOAN_MANAGER")))
        {
            sql += "  and c.city.name = '${user.city.name}'  "
        }
        else
        {
            if (city && city != 'null')
            {
                sql += "  and c.city.name = '${city}'  "
            }
        }

        if (contract)
        {
            sql += "  and oc.contract.serialNumber = '${contract}'   "
        }
        if (endDate)
        {
            sql += " and CONVERT(varchar(100), b.endTime, 120) like '${endDate}%'  "
        }
        if (jqDate)
        {
            sql += " and CONVERT(varchar(100), o.jqDate, 120) like '${jqDate}%'  "
        }
        if (jqStatus && jqStatus != 'null')
        {
            sql += "  and o.jqStatus = '${jqStatus}'   "
        }
        sql += " and o.type.name = '抵押贷款' and o.user.cellphone not in ('13718807260','18334787364','15801173559','13581657148','15201108192','15811351299','13831182365','18811374407','18513603065') and o.status != 'Failed' and o.isTest = false"
        sql += " and oc.contract.type.name='借款合同' and o.actualLendingDate is not null "
        println sql
        def ids
        if (report == "yes")
        {
            ids = Opportunity.executeQuery(sql + " order by o.id")
        }
        else
        {
            ids = Opportunity.executeQuery(sql + " order by o.id", [max: max, offset: offset])
        }
        def count = Opportunity.executeQuery(sql + " order by o.id ").size()
        def listReport = []
        def map
        ids.each {
            map = [:]
            def opp = Opportunity.findById(it)
            def sdf = new SimpleDateFormat("yyyy-MM-dd")
            //1订单号
            def serialNumber = opp.serialNumber
            //2城市
            def cityName = opp.houses[0].city.name
            //3产品类型
            def productTypeName = opp.product.name
            //4收息方式
            def interestPaymentMethod = opp.interestPaymentMethod.name
            //5借款人姓名
            def allFullName = opp.fullName + "、"
            opp.contacts.each {
                if (it.type.name != "借款人")
                {
                    allFullName += it.contact.fullName + "、"
                }

            }
            allFullName = allFullName.substring(0, allFullName.lastIndexOf("、"))
            //6合同编号
            def contractNumber = OpportunityContract.find("from OpportunityContract where opportunity.id = ${opp.id} and contract.type.name = '借款合同'")?.contract?.serialNumber
            //7抵押物位置
            def address = opp.houses[0].address
            //8抵押类型
            def loanType = opp.houses[0].mortgageType?.name
            //9抵押率
            def loanToValue = opp.houses[0].loanToValue
            //10放款通道
            def door
            //11放款账号
            def account

            def fieldsList = OpportunityFlexFieldCategory.findAllByOpportunity(opp)?.fields
            fieldsList.each {
                it.each {
                    if (it.name == "放款通道")
                    {
                        door = it.value
                    }
                    if (it.name == "放款账号")
                    {
                        account = it.value
                    }
                }
            }
            //12实际放款金额
            def actualLoanAmount = opp.actualLoanAmount == null ? opp.actualAmountOfCredit : opp.actualLoanAmount
            //13实际放款日期
            def loanDate1 = sdf.format(opp.actualLendingDate)
            //14实际借款期限
            def actualLoanDuration = opp.actualLoanDuration
            //15到期日期
            def endDate1 = sdf.format(opp.bills?.endTime[0])
            //16 综合息费/月	利息/月+服务费率/月s
            def combinedRatio = 0
            //17 月利息	基本费率/月+归到月息的加息项/月
            def monthlyInterest = 0
            //18 服务费率/月	按月取
            def serviceCharge = 0
            //19 渠道返费率/月	按月取
            def commissionRate = 0
            //20 渠道费代收方式	费用模块中渠道返费费率的收费方式----按月收、一次性收
            def commissionPaymentMethod = ""

            def bankAccount1 = OpportunityFlexField.findByNameAndCategory("债转账号", OpportunityFlexFieldCategory.findByOpportunityAndFlexFieldCategory(opp, FlexFieldCategory.findByName("资金渠道")))?.value

            opp.interest.each {
                def productName = it.productInterestType.name
                def notInList = ['意向金', '展期费', '早偿违约金', '本金违约金', '利息违约金', '本金']
                if (!notInList.contains(productName))
                {
                    if (productName == "基本费率")
                    {
                        if (!it.installments)
                        {
                            monthlyInterest += it.rate / actualLoanDuration
                        }
                        else
                        {
                            monthlyInterest += it.rate
                        }
                    }
                    else if (productName == "服务费费率")
                    {
                        if (!it.installments)
                        {
                            serviceCharge += it.rate / actualLoanDuration
                        }
                        else
                        {
                            serviceCharge += it.rate
                        }
                    }
                    else if (productName == "渠道返费费率")
                    {

                        if (!it.installments)
                        {
                            commissionRate += it.rate / actualLoanDuration
                            commissionPaymentMethod = "一次性"
                        }
                        else
                        {
                            commissionRate += it.rate
                            commissionPaymentMethod = "按月"
                        }
                    }
                    else
                    {
                        if (it.contractType?.name == "借款合同")
                        {
                            if (!it.installments)
                            {
                                monthlyInterest += it.rate / actualLoanDuration
                            }
                            else
                            {
                                monthlyInterest += it.rate //费率金额 月
                            }
                        }
                        else if (it.contractType?.name == "委托借款代理服务合同")
                        {
                            if (!it.installments)
                            {
                                serviceCharge += it.rate / actualLoanDuration
                            }
                            else
                            {
                                serviceCharge += it.rate //费率金额 月
                            }
                        }
                        else
                        {
                            if (!it.installments)
                            {
                                monthlyInterest += it.rate / actualLoanDuration
                            }
                            else
                            {
                                monthlyInterest += it.rate //费率金额 月
                            }
                        }
                    }

                }

            }
            combinedRatio += monthlyInterest + serviceCharge
            //保留两位小数
            def toBigDecimal = { rate ->
                if (rate == "0" || rate == 0)
                {
                    return "0"
                }
                else
                {
                    rate = new BigDecimal(rate).setScale(9, java.math.BigDecimal.ROUND_HALF_UP).doubleValue()
                    return rate
                }

            }
            map.serialNumber = serialNumber
            map.area = cityName
            map.productType = productTypeName
            map.interestType = interestPaymentMethod
            map.fullName = allFullName
            map.contractSerialNumber = contractNumber
            map.address = address
            map.sort = loanType
            map.loanToValue = toBigDecimal(loanToValue)
            map.door = door
            map.account = account
            map.bankAccount1 = bankAccount1
            map.actualLoanAmount = actualLoanAmount
            map.actualLendingDate = loanDate1
            map.actualLoanDuration = actualLoanDuration
            map.endDate = endDate1
            map.combinedRatio = toBigDecimal(combinedRatio)
            map.monthlyInterest = toBigDecimal(monthlyInterest)
            map.serviceCharge = toBigDecimal(serviceCharge)
            map.commissionRate = toBigDecimal(commissionRate)
            map.commissionPaymentMethod = commissionPaymentMethod
            map.jqStatus = opp?.jqStatus
            map.jqDate = opp?.jqDate?.format("yyyy-MM-dd")
            listReport.add(map)

        }
        def listTitle = ["订单编号", "区域", "产品类型", "收息方式", "借款人姓名", "合同编号", "抵押物位置", "抵押顺位", "抵押率(%)", "放款模式", "放款账户", "债转账户", "借款金额（万元）", "放款日期", "借款期限（月）", "到期日期", "综合息费/月(%)", "月利息(%)", "服务费率/月(%)", "渠道返费率/月(%)", "渠道费代收方式", "是否结清", "结清日期"]
        if (report == "yes")
        {
            /*def format = ReportFormat.get(response.format)?:ReportFormat.HTML
            format = 'PDF'
            def model = [format:format, data:listReport]
            render(view:"loanReport.jrxml",model:model)*/
            Map parameters = [:]
            jasperForPDF("opportunityStatistics/loanReport.jrxml", "loanReport", listReport, parameters)
            return null
        }
        else
        {
            respond listReport, model: [list: listReport, count: count, params: params, listTitle: listTitle]
        }
    }

    /** @Description 导出PDF文件* @Params filepath , fileName , listReport , paramsters
     * @Return null* @Author Nagelan* @DateTime 2018/9/20 0020 10:16
     */
    def jasperForPDF(def filePath, def fileName, def listReport, def parameters)
    {
        def opts = new JasperReportDef(name: filePath, //the name of jrxml or compiled .jasper file
                                       fileFormat: ReportFormat.PDF,
                                       parameters: parameters, //pass whatever parameter needed.
                                       reportData: listReport)
        def view = jasperService.getView(opts.name)
        def model = [:]
        model.putAll(opts.parameters)
        model.format = opts.fileFormat
        if (opts.reportData != null)
        {
            model.data = opts.reportData
        }
        view.setupFormat(model)
        response.setHeader("Content-Disposition", "attachment;filename=${fileName}.pdf")
        response.setContentType("application/pdf")
        def out = jasperService.generateReport(opts)
        response.setContentLength(out.size())
        def jasperPrint = view.fillReport(model)
        def exporter = new JRPdfExporter()
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint)
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream())
        //response.setCharacterEncoding("UTF-8")
        exporter.exportReport()
        def sos = response.getOutputStream()
        out.writeTo(sos)
        sos.flush()
        out.flush()
        sos.close()
        out.close()
    }
}
